//MountManager - the program for easy mounting of storage devices in Linux
//Copyright (C) 2007-2008 Tikhonov Sergey
//
//This file is part of MountManager Core
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <QStringList>
#include <QDebug>
#include "diskdevice.h"
#include "diskhal.h"
#include "const.h"

DiskHal::DiskHal(bool deb,QObject *parent) : QObject(parent) {
	debug = deb;
	
	// Create interface to get information from Hal
	informationCenter = new QDBusInterface(HAL_SERVICE,HAL_PATH,HAL_INTERFACE,QDBusConnection::systemBus());
	
	// Check interace and write result to log 
	if (informationCenter->isValid()) {
		if (debug) qDebug("[G] DBus interface was created");
	} else
		if (debug) qDebug("[E] DBus interface was not created");
	
	QDBusReply<QStringList> allDevicesReply = informationCenter->call("GetAllDevices");
	allDevicesReply.isValid() ? qDebug("[G] All devices were recieved") : qDebug("[E] Cannot receive all devices");
	
	foreach (QString udi,allDevicesReply.value())
		addDevice(udi);

	foreach (DiskDevice *device,devicesList)
		foreach (DiskDevice *parentDevice,devicesList)
			if (parentDevice->udi() == device->parentUdi()) {
				device->setParent(parentDevice);
				break;
			}
	
	
	informationCenter->connection().connect(HAL_SERVICE,HAL_PATH,HAL_INTERFACE,
							"DeviceAdded",this,SLOT(addDevice(const QString&)));
	informationCenter->connection().connect(HAL_SERVICE,HAL_PATH,HAL_INTERFACE,
							"DeviceRemoved",this,SLOT(removeDevice(const QString&)));
}

DiskHal::~DiskHal() {
	delete informationCenter;
	foreach (DiskDevice *device,devicesList)
		delete device;
}

void DiskHal::addDevice(const QString &udi) {
	// Skip not storage device
	QDBusInterface *storageInterface = new QDBusInterface(HAL_SERVICE,
					udi,HAL_DEVICE_INTERFACE,QDBusConnection::systemBus());
	QDBusReply<QString> blockReply = storageInterface->call("GetPropertyString","block.device");
	QString name = blockReply.value();
	if (name.isEmpty())  {
		delete storageInterface;
		return;
	}

	DiskDevice *storageDevice = new DiskDevice(storageInterface,udi);
	storageDevice->setFstabItem(fstabItem(storageDevice));

	foreach (DiskDevice *parentDevice,devicesList)
		if (parentDevice->udi() == storageDevice->parentUdi()) {
			storageDevice->setParent(parentDevice);
			break;
		}
	
	if (debug) qDebug() << "[I] Storage device was detected:" << name;
	devicesList.append(storageDevice);

	emit (deviceAdded(storageDevice));
}

void DiskHal::removeDevice(const QString &udi) {
	DiskDevice *removedDevice = deviceByUdi(udi);
	if (removedDevice != 0) {
		if (debug)  qDebug() << "[I] Storage device was removed:" << removedDevice->blockName();
		emit (deviceRemoved(removedDevice));
		devicesList.removeAll(removedDevice);
	}
}

int DiskHal::count() {
	return devicesList.count();
}

QList<DiskDevice *>&  DiskHal::devices() {
	return devicesList;
}

DiskDevice* DiskHal::deviceByUdi(const QString& udi) {
	foreach (DiskDevice *device,devicesList)
		if (device->udi() == udi)
			return device;
	return 0;
}

DiskDevice* DiskHal::deviceByBlockName(const QString& blockName) {
	foreach (DiskDevice *device,devicesList)
		if (device->blockName() == blockName)
			return device;
	return 0;
}

DiskDevice* DiskHal::deviceByUuid(const QString& uuid) {
	foreach (DiskDevice *device,devicesList)
		if (device->uuid() == uuid)
			return device;
	return 0;	
}
